package com.taobao.dao;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.util.EntityUtils;

import com.taobao.pojo.Config;
import com.taobao.pojo.HttpContext;

public abstract class CommonDao {

    private DefaultHttpClient getHttpClient(String url) {
        int time_out = Integer.parseInt(Config.time_out);
        DefaultHttpClient client = new DefaultHttpClient();
        client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, time_out);
        client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, time_out);
        if (url.contains("taobao.com") || url.contains("alipay.com")) {
            client.setCookieStore(Config.alipayCs);
        } else {
            client.setCookieStore(Config.cookieStore);
        }
        return client;
    }

    public Object postRequest(String url, String referUrl, Map<String, String> params) throws Exception {
        DefaultHttpClient client = getHttpClient(url);
        try {
            HttpPost post = new HttpPost(url);
            if (referUrl != null) {
                post.setHeader("Referer", referUrl);
            }
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            Set<String> keys = params.keySet();
            for (Iterator<String> iterator = keys.iterator(); iterator.hasNext();) {
                String key = (String) iterator.next();
                nvps.add(new BasicNameValuePair(key, params.get(key)));
            }
            post.setEntity(new UrlEncodedFormEntity(nvps, "GBK"));

            HttpResponse response = client.execute(post);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                return this.process(getHttpContext(client, response, false));
            } else if (statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
                Header[] hs = response.getHeaders("Location");
                String locaiton = hs[0].getValue();
                return this.getRequest(locaiton);
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            client.getConnectionManager().shutdown();
            throw new Exception("CommonDao.postRequest Error " + this.getClass());
        }
    }

    public Object getRequest(String url) throws Exception {
        DefaultHttpClient client = getHttpClient(url);
        try {
            HttpGet get = new HttpGet(url);
            HttpResponse response = client.execute(get);

            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                return this.process(getHttpContext(client, response, false));
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            client.getConnectionManager().shutdown();
            throw new Exception("CommonDao.getRequest Error " + this.getClass());
        }
    }

    public Object getRequestForStream(String url) throws Exception {
        DefaultHttpClient client = getHttpClient(url);
        try {
            HttpGet get = new HttpGet(url);
            HttpResponse response = client.execute(get);

            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                return this.process(getHttpContext(client, response, true));
            } else {
                return null;
            }
        } catch (Exception e) {
            client.getConnectionManager().shutdown();
            throw new Exception("CommonDao.getRequestForStream Error " + this.getClass());
        }
    }

    private HttpContext getHttpContext(DefaultHttpClient client, HttpResponse response, boolean forStream) throws ParseException, IOException {
        try {
            HttpContext context = new HttpContext();
            HttpEntity entity = response.getEntity();
            context.setCookieStore(client.getCookieStore());
            context.setEntity(entity);
            if (!forStream) {
                context.setHtml(EntityUtils.toString(entity));
            }
            return context;
        } catch (Exception e) {
            throw new ParseException("CommonDao.getHttpContext Error " + this.getClass());
        }
    }

    public abstract Object process(HttpContext context) throws Exception;
}
